<template>
  <div>
    <div class="upload">
      <vuedraggable v-model="imageList" class="upload">
        <div v-for="(item, index) in imageList" :key="index" class="uploadImg">
          <img class="thumbnail" :src="item.url" alt="" />
          <div class="shadow">
            <div class="icon" @click="handlePictureCardPreview(item, index)">
              <i class="el-icon-zoom-in up"></i>
            </div>
            <div class="icon" @click="handleRemove(item, index)">
              <i class="el-icon-delete up"></i>
            </div>
          </div>
        </div>
      </vuedraggable>
      <el-upload
          v-if="couldUpload"
          ref="elUploadRef"
          :accept="accept"
          :action="fileUploadUrl"
          :auto-upload="false"
          :on-change="imageChange"
          :multiple="multiple"
          :list-type="type"
          :drag="drag"
          :limit="limit"
          :show-file-list="false"
      >
        <i class="el-icon-plus"></i>
      </el-upload>
    </div>
    <div class="tip">
      请上传
      <span>图片</span>
      格式文件 ，且文件大小不超过
      <span>{{ size }}</span>
      MB
      <span>{{ tip }}</span>
    </div>
    <v-cropper
        :autoCropWidth="autoCropWidth"
        :autoCropHeight="autoCropHeight"
        :fixedBox="fixedBox"
        :fixed="fixed"
        :round="round"
        :previewWidth="previewWidth"
        :canMoveBox="canMoveBox"
        ref="cropper"
        @success="handleAvatarSuccess"
        :size="size"
        :mode="mode"
        :maxImgSize="maxImgSize"
        :enlarge="enlarge"
    ></v-cropper>
    <div v-if="type == 'video'"></div>
    <el-image-viewer
        style="z-index:9999"
        v-if="visible"
        :url-list="urls"
        :fixedNumber="fixedNumber"
        :outputType="outputType"
        :initial-index="initialIndex"
        teleported
        hide-on-click-modal
        :on-close="onClose"
    ></el-image-viewer>
  </div>
</template>
<script>
import VCropper from "@/components/cropper/index.vue"
import vuedraggable from "vuedraggable"

export default {
  name: "FortressUpload",
  components: { vuedraggable, VCropper, "el-image-viewer": () => import("element-ui/packages/image/src/image-viewer") },
  //
  props: {
    type: {
      type: String,
      default: "picture-card",
    },
    // 上传图片限制个数
    limit: {
      type: Number,
      default: 1,
    },
    value: {
      type: [String, Array],
      default: "",
    },
    // 是否多选
    multiple: {
      type: Boolean,
      default: false,
    },
    // 是否拖拽
    drag: {
      type: Boolean,
      default: false,
    },
    // 上传文件类型
    accept: {
      type: String,
      default: "",
    },
    // 默认生成截图框宽度
    autoCropWidth: {
      type: Number,
      default: 200,
    },
    // 默认生成截图框高度
    autoCropHeight: {
      type: Number,
      default: 200,
    },
    //固定截图框大小[宽，高]，默认不允许改变
    fixedBox: {
      type: Boolean,
      default: false,
    },
    //是否开启截图框宽高固定比例
    fixed: {
      type: Boolean,
      default: true,
    },
    // 预览的图片是圆形还是方形
    round: {
      type: Boolean,
      default: false,
    },
    // 预览宽度
    previewWidth: {
      type: Number,
      default: 150,
    },
    // 截图框的宽高比例
    fixedNumber: {
      type: Array,
      default: () => [1, 1],
    },
    outputType: {
      type: String,
      default: "png",
    },
    // 上传的文件大小限制
    size: {
      type: Number,
      default: 3,
    },
    //截图框能否拖动
    canMoveBox: {
      type: Boolean,
      default: true,
    },
    //图片默认渲染方式
    mode: {
      type: String,
      default: "contain",
    },
    // 上传图片最大宽度和高度
    maxImgSize: {
      type: Number,
      default: 2000,
    },
    enlarge: {
      type: Number,
      default: 1,
    },
    tip: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      fileUploadUrl: window.$conf.commonConf.baseUrl + "/system/oss/upload", // 上传图片的地址
      fileList: [],
      visible: false,
      disabled: false,
      fileUrl: "",
      imageList: [],
      initialIndex: 0,
      urls: [],
      couldUpload: true,
    }
  },
  created() {},
  methods: {
    urlsChange() {
      this.urls = this.imageList.map(item => item.url)
    },
    couldUploadChange() {
      if (this.disabled) {
        this.couldUpload = false
      } else if (this.limit == -1) {
        this.couldUpload = true
      } else {
        this.couldUpload = this.imageList.length < this.limit
      }
    },
    handleCrop(file) {
      this.$nextTick(() => {
        this.$refs.cropper.handleChangeUpload(file)
      })
    },
    imageChange(file) {
      this.handleCrop(file)
      this.$refs.elUploadRef.clearFiles()
    },
    fileChange(file, fileList) {
      this.fileList = fileList.slice(-3)
      // this.$emit("input", fileList)
    },
    handlePictureCardPreview(item, index) {
      this.initialIndex = index
      this.visible = true
    },
    handleRemove(item, index) {
      this.imageList.splice(index, 1)
      this.couldUploadChange()
      this.$emit("input", this.imageList.map(item => item.url).join(","))
    },
    handleAvatarSuccess(res) {
      if (res && res.code == 0) {
        this.$nextTick(() => {
          this.imageList = this.imageList.concat([{ url: res.data.url }])
          this.urlsChange()
          this.couldUploadChange()

          if (this.limit != 1) {
            this.$emit("input", this.imageList.map(item => item.url).join(","))
          } else {
            this.$emit("input", res.data.url)
          }
        })
      }
    },
    onClose() {
      this.visible = false
    },
  },
  watch: {
    type: {
      handler(val) {
        if (val === "text") {
          this.drag = true
        }
      },
      immediate: true,
    },
    value: {
      handler(val) {
        if (val) {
          if (this.limit != 1) {
            this.imageList = (Array.isArray(val) ? val : val.split(",")).map(item => {
              if (typeof item == "string") {
                return {
                  url: item,
                }
              }
              return item
            })
          } else {
            this.imageList = [
              {
                url: val,
              },
            ]
          }
        } else {
          this.imageList = []
        }
      },
      immediate: true,
    },
    imageList: {
      handler(val, old) {
        if (val) {
          this.urlsChange()
          this.couldUploadChange()
        }

        if (JSON.stringify(old) !== JSON.stringify(val)) {
          this.$emit("input", val.map(item => item.url).join(","))
        }
      },
      immediate: true,
      deep: true,
    },
  },
}
</script>
<style lang="scss" scoped>
.upload {
  display: flex;
  flex-wrap: wrap;
  .uploadImg {
    position: relative;
    width: 148px;
    height: 148px;
    margin-right: 10px;
    margin-bottom: 10px;
    border-radius: 10px;
    overflow: hidden;
    .thumbnail {
      cursor: pointer;
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
    .shadow {
      display: none;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      z-index: 9;
      gap: 25px;
      .icon {
        display: none;
        cursor: pointer;
        color: #fff;
        .up {
          display: none;
          font-size: 20px;
        }
      }
    }
    &:hover {
      .thumbnail {
        cursor: pointer;
        width: 100%;
        object-fit: cover;
      }
      .shadow {
        display: block;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-color: rgba(0, 0, 0, 0.6);
        display: flex;
        justify-content: center;
        align-items: center;
        z-index: 9;
        gap: 25px;
        .icon {
          display: block;
          cursor: pointer;
          color: #fff;
          .up {
            display: block;
            font-size: 20px;
          }
        }
      }
    }
  }
}
.tip {
  font-size: 12px;
  span {
    color: rgb(245, 108, 108);
    &:last-child {
      color: #787a7d;
    }
  }
}
</style>
